#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> 
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include "zynq_dna_uio.h"
#include "zlog.h"


#define ZYNQ_DNA_UIO_DEV 				"/dev/uio3"
#define ZYNQ_DNA_UIO_ADDR     	 		"/sys/class/uio/uio3/maps/map0/addr"
#define ZYNQ_DNA_UIO_SIZE      			"/sys/class/uio/uio3/maps/map0/size"

#define ZYNQ_DNA_H_4BYTES_REG			0
#define ZYNQ_DNA_M_4BYTES_REG			1
#define ZYNQ_DNA_L_4BYTES_REG			2


zynq_dna_handle		dna_dev;


void zynq_dna_axi_init(sys_cfg_info *sys, zynq_dna_handle *dna)
{
	char dna_uio_addr_buf[18], dna_uio_size_buf[18];
	int dna_uio_fd, dna_addr_fd, dna_size_fd;
	
	dna_uio_fd 	= open(ZYNQ_DNA_UIO_DEV, O_RDWR);
    dna_addr_fd = open(ZYNQ_DNA_UIO_ADDR, O_RDONLY);
    dna_size_fd = open(ZYNQ_DNA_UIO_SIZE, O_RDONLY);
	if (dna_addr_fd < 0 || dna_size_fd < 0 || dna_uio_fd < 0) {
		dzlog_error("zynq dna uio device file open error!");
		perror("zynq dna uio device file open error!\n");
        exit(EXIT_FAILURE);
    }

	read(dna_addr_fd, dna_uio_addr_buf, sizeof(dna_uio_addr_buf));
    read(dna_size_fd, dna_uio_size_buf, sizeof(dna_uio_size_buf));

	dna->dna_axi_uio_fd = dna_uio_fd;
	dna->dna_axi_base_addr = strtoul(dna_uio_addr_buf, NULL, 16);	//16代表16进制读取
    // dna->dna_axi_addr_size = strtoul(dna_uio_size_buf, NULL, 16);	//16代表16进制读取
    dna->dna_axi_addr_size = 0x10000;

	dna->dna_axi_virt_addr =  mmap(NULL, dna->dna_axi_addr_size, PROT_READ | PROT_WRITE,
								MAP_SHARED, dna->dna_axi_uio_fd, 0);
	
    if (dna->dna_axi_virt_addr == MAP_FAILED) {
        fprintf(stderr, "dna->dna_axi_base_addr mmap: %s\n", strerror(errno));
		dzlog_error("dna->dna_axi_base_addr mmap failed!");
        exit(FAILURE);
    }

	printf("dna_axi_uio_fd is %d\n", dna->dna_axi_uio_fd);
	printf("dna_axi_base_addr is %#0x\n", dna->dna_axi_base_addr);
	printf("dna_axi_addr_size is %#0x\n", dna->dna_axi_addr_size);
	printf("dna->bz_axi_virt_addr is %p\n", dna->dna_axi_virt_addr);
	printf("############################################################\n");
}


inline __attribute__((always_inline)) uint32_t dna_axi_reg_get(zynq_dna_handle *pdna, uint32_t offset) 
{
   return *(pdna->dna_axi_virt_addr + offset);
}



void zynq_dna_uuid_get(sys_cfg_info *sys, zynq_dna_handle *pdna)
{
	zynq_dna_axi_init(sys, pdna);
	
	sys->zynqmp_uuid[2] = dna_axi_reg_get(pdna, ZYNQ_DNA_H_4BYTES_REG);
	sys->zynqmp_uuid[1] = dna_axi_reg_get(pdna, ZYNQ_DNA_M_4BYTES_REG);
	sys->zynqmp_uuid[0] = dna_axi_reg_get(pdna, ZYNQ_DNA_L_4BYTES_REG);

	sprintf(sys->dev_uuid, "%08x%08x%08x", sys->zynqmp_uuid[2], sys->zynqmp_uuid[1], sys->zynqmp_uuid[0]);
	sys->dev_uuid[25] = '\0';
	printf("zynqmp uuid sys->dev_uuid is %s\n", sys->dev_uuid);
}

